/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#pragma once

#include <面/面.h>
#include <物体/物体.h>
#include <材质/预设材质.h>

#include "节点数据声明.h"
#include "当前默认操作数据.h"



#define _DEF_变换插座创建_ DEF_创建Vec3插座_v1_I(u"位置"); DEF_创建Vec3插座_v1_I(u"旋转"); DEF_创建Vec3插座_v1_I(u"缩放");
#define _DEF_变换属性创建_                                                                                         \
	if (m_Ob == nullptr) {                                                                                         \
		m_Ob = f_node_网格节点创建物体数据(m_Ctx);                                                                 \
		f_get输出插座(1)->f_setData(m_Ob);                                                                         \
		f_NodeCtx_录物体类节点(this);                                                                              \
	}                                                                                                              \
	m_位置 = f_alloc_Vec3Prop(&m_Ob->m_变换.position, u"位置");                                                    \
	m_旋转 = f_alloc_Vec3Prop(&m_Ob->m_变换.rotation, u"旋转");                                                    \
	m_缩放 = f_alloc_Vec3Prop(&m_Ob->m_变换.scale, u"缩放");                                                       \
	m_位置.m_私有 = true;                                                                                          \
	m_旋转.m_私有 = true;                                                                                          \
	m_缩放.m_私有 = true;                                                                                          \






typedef struct {
	S_单色材质* m_描边;
	S_单色材质* m_面;
	S_单色材质* m_线;
}S_单色材质包;

enum E_虚拟体类型 : uint8 {
	E_交叉轴,
	E_方向轴,
	E_线框球,
};



API_EXPORT S_物体* f_node_初始化单虚拟体网格(S_设备环境& ctx);
API_EXPORT void f_node_释放虚拟体网格();


API_EXPORT void f_node_物体绘制属性设置(S_物体* ob);
API_EXPORT void f_node_设置物体光照材质(S_物体* ob);




API_EXPORT void f_node_构建多边形网格对象(S_物体* ob, S_设备环境& ctx);
API_EXPORT void f_node_创建粒子物体数据(S_物体* ob, S_设备环境& ctx);
API_EXPORT void f_node_构建物体模型(S_物体* ob, S_设备环境& ctx);

API_EXPORT void f_node_设置物体权重材质(S_物体* ob);



API_EXPORT S_物体* f_node_网格节点创建物体数据(S_设备环境& ctx);
API_EXPORT S_物体* f_node_网格节点创建连续线物体数据(S_设备环境& ctx);
API_EXPORT S_物体* f_node_网格节点创建线段物体数据(S_设备环境& ctx);
API_EXPORT S_物体* f_node_网格节点创建点物体数据(S_设备环境& ctx);
API_EXPORT S_物体* f_node_构建曲线物体数据(S_设备环境& ctx);



API_EXPORT void f_node_创建模型物体组(S_OBArray* 物体, uint32 num, E_物体类型 type, S_设备环境& ctx, E_物体类型 附加类型 = E_物体类型::t_空);
API_EXPORT void f_node_销毁模型网格(S_物体* ob);
API_EXPORT void f_node_创建纹理组(S_TexArray* 纹理, uint32 num, S_设备环境& ctx);
API_EXPORT void f_node_销毁纹理组(S_TexArray* 纹理);



API_EXPORT void	f_node_物体节点创建物体数据_单色明暗(S_物体* ob);
API_EXPORT void	f_node_将现有物体包装成骨骼网格(S_设备环境& ctx, S_物体* 骨骼, S_物体* 骨节);

API_EXPORT S_物体* f_node_创建虚拟体(S_设备环境& ctx, E_虚拟体类型 类型);
API_EXPORT S_物体* f_node_创建虚线(S_设备环境& ctx);
API_EXPORT S_物体* f_node_创建包围盒虚拟体(S_设备环境& ctx);
API_EXPORT S_物体* f_node_创建虚拟体网格物体(S_设备环境& ctx, E_物体类型 类型);
API_EXPORT void    f_node_创建平行光虚拟体(S_物体* ob);
API_EXPORT void    f_node_创建点光源虚拟体(S_物体* ob);
API_EXPORT void    f_node_创建聚光灯虚拟体(S_物体* ob);
API_EXPORT void    f_node_创建区域光虚拟体(S_物体* ob);


API_EXPORT void	f_node_移除虚拟体(S_物体* ob);
API_EXPORT void	f_node_设置灯光虚拟网格类型(S_物体* ob, E_物体类型 类型);
API_EXPORT void	f_node_设置灯光虚拟网格范围(S_物体* ob, const vec2& r);
API_EXPORT void    f_node_设置点光源虚拟体绘制(S_VkDrawIndirectCommand& 中心圆间接, S_VkDrawIndirectCommand& 边界线间接, S_VkDrawIndirectCommand& 方向线间接, uint32 offset);
API_EXPORT void    f_node_设置聚光灯虚拟体绘制(S_VkDrawIndirectCommand& 中心圆间接, S_VkDrawIndirectCommand& 边界线间接, S_VkDrawIndirectCommand& 方向线间接, uint32 offset);
API_EXPORT void    f_node_设置方形区域光虚拟体绘制(S_VkDrawIndirectCommand& 中心圆间接, S_VkDrawIndirectCommand& 边界线间接, S_VkDrawIndirectCommand& 方向线间接, uint32 offset);
API_EXPORT void    f_node_设置圆形区域光虚拟体绘制(S_VkDrawIndirectCommand& 中心圆间接, S_VkDrawIndirectCommand& 边界线间接, S_VkDrawIndirectCommand& 方向线间接, uint32 offset);
API_EXPORT void    f_node_设置摄像机虚拟体绘制(S_VkDrawIndirectCommand& 中心圆间接, S_VkDrawIndirectCommand& 边界线间接, S_VkDrawIndirectCommand& 方向线间接, uint32 offset);


API_EXPORT S_物体* f_node_创建摄像机虚拟体(S_物体* ob);
API_EXPORT void    f_node_设置摄像机虚拟网格(S_物体* ob, S_摄像机* 摄像机);

API_EXPORT void    f_node_创建立方体虚拟体(S_物体* ob);
API_EXPORT void    f_node_设置立方体虚拟体绘制(S_VkDrawIndirectCommand& 中心圆间接, S_VkDrawIndirectCommand& 边界线间接, S_VkDrawIndirectCommand& 方向线间接, uint32 offset);
API_EXPORT void    f_node_设置立方体虚拟网格(S_物体* ob, const vec3& size);
API_EXPORT void    f_node_设置球体虚拟网格(S_物体* ob, const vec3& size);
API_EXPORT void    f_node_设置链接线方体虚拟网格(S_物体* ob, const vec3& size, const vec3& loc);



API_EXPORT S_物体* f_node_get多元素虚拟体根物体(S_设备环境& ctx);
API_EXPORT S_物体* f_node_get单元素虚拟体根物体(S_设备环境* ctx);


API_EXPORT S_物体* f_node_创建UV辅助操作虚拟体(S_设备环境& ctx);
API_EXPORT void    f_node_设置UV操作虚拟体类型(S_物体* ob, uint32 type);
API_EXPORT S_物体* f_node_创建单元素虚拟体(S_设备环境& ctx);
API_EXPORT void    f_node_设置单元素虚拟体类型(S_物体* ob, uint32 type);
API_EXPORT S_物体* f_node_创建圆柱UV辅助操作虚拟体(S_设备环境& ctx);
API_EXPORT S_物体* f_node_创建圆柱封套虚拟体(S_设备环境& ctx);



Inline void f_node_物体添加到主场景(S_物体* ob) {
	f_scene_添加物体(f_NodeCtx_get默认场景(), ob);
	S_节点数据::m_全局物体set.insert(ob);
}

Inline void f_node_物体从主场景中移除(S_物体* ob) {
	f_scene_移除物体(f_NodeCtx_get默认场景(), ob);
	S_节点数据::m_全局物体set.erase(ob);
}


Inline void f_node_物体添加到主场景(std::vector<S_物体*>& obs) {
	f_scene_添加物体(f_NodeCtx_get默认场景(), obs);
	S_节点数据::m_全局物体set.insert(obs.begin(), obs.end());
}

Inline void f_node_物体从主场景中移除(std::vector<S_物体*>& obs) {
	f_scene_移除物体(f_NodeCtx_get默认场景(), obs);
	for(auto& e : obs) S_节点数据::m_全局物体set.erase(e);
}

API_EXPORT void f_node_修改物体名称(S_物体* ob, const S_Props& name);


Inline void f_node_物体添加到主场景(S_OBArray* obs) {
	for (uint32 i = 0; i < obs->count; ++i) {
		f_node_物体添加到主场景(obs->ptr_userData[i]);
	}
}

Inline void f_node_物体从主场景中移除(S_OBArray* obs) {
	for (uint32 i = 0; i < obs->count; ++i) {
		f_node_物体从主场景中移除(obs->ptr_userData[i]);
	}
}

API_EXPORT std::u16string	f_node_物体名称修改(S_Object* ob, const std::u16string& name);

API_EXPORT void    f_node_物体添加到全局容器(S_Object* ob, bool 自动重命名 = true);
inline void    f_node_物体添加到全局容器(S_OBArray* obs) {
	for (uint32 i = 0; i < obs->count; ++i) {
		f_node_物体添加到全局容器(obs->ptr_userData[i]);
	}
}

API_EXPORT void    f_node_从全局容器移除物体(S_物体* ob);
inline void    f_node_从全局容器移除物体(S_OBArray* obs) {
	for (uint32 i = 0; i < obs->count; ++i) {
		f_node_从全局容器移除物体(obs->ptr_userData[i]);
	}
}

API_EXPORT S_物体* f_node_从全局物体容器查找物体(std::u16string name);


API_EXPORT S_Object* f_node_创建渲染世界(std::u16string name, S_设备环境& ctx);
API_EXPORT S_Object* f_node_删除渲染世界(const std::u16string& name);


API_EXPORT S_Object* f_node_创建渲染层(S_Object* 世界, std::u16string name, S_设备环境& ctx);
API_EXPORT S_Object* f_node_删除渲染层(S_Object* 世界, const std::u16string& name);

API_EXPORT void f_node_物体添加到渲染层(S_Object* 层, S_物体* ob);
API_EXPORT void f_node_物体从渲染层移除(S_Object* 层, S_物体* ob);

API_EXPORT void f_node_销毁所有渲染层(S_Object* 世界);
API_EXPORT void f_node_销毁所有渲染世界();



API_EXPORT S_单色材质包	f_node_get骨骼可视材质(S_设备环境& ctx);
API_EXPORT void			f_node_回收骨骼可视材质(S_单色材质包 包);
API_EXPORT S_材质管线*			f_node_getVecSphere材质(S_设备环境& ctx);
API_EXPORT void			f_node_回收VecSphere可视材质(S_材质管线* 材质);


API_EXPORT S_骨骼插座数据* f_node_创建编辑骨骼();

API_EXPORT void f_node_创建物体(S_OBArray* obs);
API_EXPORT void f_node_删除物体(S_OBArray* obs);
API_EXPORT void f_node_删除物体(std::vector<S_物体*>& obs);
API_EXPORT void f_node_删除物体(S_物体* ob);
API_EXPORT bool f_node_销毁物体();


API_EXPORT S_着色器创建配置 f_node_轮廓线管配置(E_几何着色类型 着色面类型);





